/**
 * 
 */
package com.kathez.studentportal.dao;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.logging.Level;

import com.kathez.CRUDOperataionType;
import com.kathez.dao.AbstractKathezDao;
import com.kathez.dao.DAOInsertResultImpl;
import com.kathez.dao.DAOResult;
import com.kathez.dao.DAOTxnCommand;
import com.kathez.entity.AbstractKathezEntity;
import com.kathez.entity.DAOOperable;
import com.kathez.studentportal.entity.Student;

/**
 * @author Balaji T
 *
 */
public class EnrollFlatFileDao extends AbstractKathezDao implements EnrollDAO{

	private File flatFile = null;
	private DAOTxnCommand enrollCommand = new EnrollCommand(this);
	private DAOTxnCommand updateCommand = new UpdateCommand(this);

	/* (non-Javadoc)
	 * @see com.kathez.dao.IKathezDao#doDataOperation(com.kathez.entity.KathezEntity, com.kathez.CRUDOperataionType)
	 */
	@Override
	public DAOResult doDataOperation(AbstractKathezEntity entityObject,
			CRUDOperataionType operationType) {
		if(entityObject != null && operationType != null){
			if(entityObject instanceof Student){
				switch(operationType){
				case ADD:
					return this.enrollCommand.execute(entityObject, false);
				case UPDATE:
					return this.updateCommand .execute(entityObject, false);
				case DELETE:

				case FETCH:	
				}
			}			
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see com.kathez.studentportal.dao.EnrollDAO#enrollStudent(com.kathez.studentportal.entity.Student)
	 */
	public DAOResult enrollStudent(Student student) {
		DAOInsertResultImpl result = null;
		if(student != null){
			flatFile = new File("Student.txt");
			OutputStream fileOutStream = null;
			OutputStreamWriter fileOutWriter = null;
			try {
				fileOutStream = new FileOutputStream(flatFile);
				fileOutWriter = new OutputStreamWriter(fileOutStream);

				fileOutWriter.write(student.getPrimaryKey().getKeysAsString());
				fileOutWriter.write(student.getFirstName());
				fileOutWriter.write(student.getLastName());
				fileOutWriter.flush();
				result = new DAOInsertResultImpl();
				result.setInsertedObject(student);					
				return result;
			} catch (FileNotFoundException e) {
				LOGGER.log(Level.SEVERE, "File Not Found "+flatFile, e);
			} catch (IOException e) {
				LOGGER.log(Level.SEVERE, "IOException while writing "+flatFile, e);
			}finally{
				try {
					fileOutWriter.close();
					fileOutStream.close();
				} catch (IOException e) {
					LOGGER.log(Level.SEVERE, "IOException while closing file "+flatFile, e);
				}finally{
					fileOutWriter = null;
					fileOutStream = null;
				}

			}
		}
		return null;
	}
	
	/* (non-Javadoc)
	 * @see com.kathez.studentportal.dao.EnrollDAO#undoEnrollStudent(com.kathez.entity.DAOOperable)
	 */
	@Override
	public DAOResult undoEnrollStudent(Student student) {
		DAOInsertResultImpl result = null;
		if(student != null){
			if(flatFile == null)
				flatFile = new File("Student.txt");
			if(!flatFile.exists()){
				result = new DAOInsertResultImpl();
				result.setInsertedObject(student);					
				return result;
			}
			OutputStream fileOutStream = null;
			OutputStreamWriter fileOutWriter = null;
			try {
				fileOutStream = new FileOutputStream(flatFile);
				fileOutWriter = new OutputStreamWriter(fileOutStream);

				fileOutWriter.write(" File Contents Undone and File is emptied");
				fileOutWriter.flush();
				result = new DAOInsertResultImpl();
				result.setInsertedObject(student);					
				return result;
			} catch (FileNotFoundException e) {
				LOGGER.log(Level.SEVERE, "File Not Found "+flatFile, e);
			} catch (IOException e) {
				LOGGER.log(Level.SEVERE, "IOException while writing "+flatFile, e);
			}finally{
				try {
					fileOutWriter.close();
					fileOutStream.close();
				} catch (IOException e) {
					LOGGER.log(Level.SEVERE, "IOException while closing file "+flatFile, e);
				}finally{
					fileOutWriter = null;
					fileOutStream = null;
				}

			}
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see com.kathez.studentportal.dao.EnrollDAO#updateStudentInfo(com.kathez.entity.BusinessOperable)
	 */
	public DAOResult updateStudentInfo(Student entity){
		return null;
	}

	/* (non-Javadoc)
	 * @see com.kathez.studentportal.dao.EnrollDAO#undoUpdateStudentInfo(com.kathez.studentportal.entity.Student)
	 */
	@Override
	public DAOResult undoUpdateStudentInfo(Student entityObject) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	protected void commit(AbstractKathezEntity entityObject, CRUDOperataionType opearationType) {
		// TODO Auto-generated method stub

	}

	@Override
	protected void rollBack(AbstractKathezEntity entityObject, CRUDOperataionType operationType) {
		if(entityObject != null && operationType != null){
			if(entityObject instanceof Student){
				switch(operationType){
				case ADD:
					this.enrollCommand.execute(entityObject, true);
				case UPDATE:
					this.updateCommand .execute(entityObject, true);
				case DELETE:

				case FETCH:	
				}
			}			
		}			
	}	

	/**
	 * @author Balaji T
	 *
	 */
	private class EnrollCommand implements DAOTxnCommand{

		private EnrollDAO enrollDAO;

		EnrollCommand(EnrollDAO dao){
			this.enrollDAO = dao;
		}

		/* (non-Javadoc)
		 * @see com.kathez.dao.DAOTxnCommand#execute(com.kathez.entity.DAOOperable, boolean)
		 */
		@Override
		public DAOResult execute(DAOOperable entityObject, boolean undo) {
			if(undo)
				return this.enrollDAO.undoEnrollStudent((Student)entityObject);
			else
				return this.enrollDAO.enrollStudent((Student)entityObject);
		}	
	}
	
	/**
	 * @author Balaji T
	 *
	 */
	private class UpdateCommand implements DAOTxnCommand {
		
		private EnrollDAO enrollDAO;

		UpdateCommand(EnrollDAO dao){
			this.enrollDAO = dao;
		}
		
		/* (non-Javadoc)
		 * @see com.kathez.dao.DAOTxnCommand#execute(com.kathez.entity.DAOOperable, boolean)
		 */
		@Override
		public DAOResult execute(DAOOperable entityObject, boolean undo) {
			if(undo)
				return this.enrollDAO.updateStudentInfo((Student)entityObject);
			else
				return this.enrollDAO.undoUpdateStudentInfo((Student)entityObject);			
		}
	}
}
